package generation.aggregation;

import generation.duration.DurationCellRepository;
import generation.methods.BasicMarkov;

import javax.swing.JSlider;

import jm.audio.Instrument;
import jm.constants.RhythmValues;
import jm.music.data.Note;
import jm.music.rt.RTLine;
import util.Utils;

public class RTMelody extends RTLine {
	private Note n = new Note(36, 0.5);
	private int pitch = 36;
	private int[] intervals = { 0, 0, 0, 4, 7, 10, 12 };
	private int[] pitches = { 60, 62, 64, 67, 69 };
	private double[] durations = { 
			RhythmValues.SEMIBREVE,
			RhythmValues.DOTTED_MINIM, 
			RhythmValues.MINIM,
			RhythmValues.DOTTED_CROTCHET, 
			RhythmValues.CROTCHET,
			RhythmValues.DOTTED_QUAVER, 
			RhythmValues.QUAVER,
			RhythmValues.DOTTED_SEMI_QUAVER, 
			RhythmValues.SEMI_QUAVER, };
	private double panPosition = 0.5;
	private double x;
	private double y;
	private String[] currentRCell;
	private String[] nextRCell;
	private boolean useCell;
	private int count;
	private BasicMarkov bm;

	/** Constructor */
	public RTMelody(Instrument[] instArray) {
		super(instArray);
		//setTempo(120);
		useCell = true;
		count = 0;
		bm =  new BasicMarkov();
	}

	public double getRhythmValueByDuration(String duration) {
		double result = 1.0;
		if (duration.equals("w")) {
			result = RhythmValues.SEMIBREVE;
		} else if (duration.equals("h")) {
			result = RhythmValues.MINIM;
		} else if (duration.equals("h*")) {
			result = RhythmValues.MINIM_TRIPLET;
		} else if (duration.equals("q")) {
			result = RhythmValues.CROTCHET;
		}  else if (duration.equals("q*")) {
			result = RhythmValues.CROTCHET_TRIPLET;
		} else if (duration.equals("i")) {
			result = RhythmValues.QUAVER;
		} else if (duration.equals("i*")) {
			result = RhythmValues.QUAVER_TRIPLET;
		} else if (duration.equals("s")) {
			result = RhythmValues.SEMI_QUAVER;
		} 
		return result;
	}

	/**
	 * Generate the next note when requested.
	 */
	public synchronized Note getNote() {
		int index = Utils.random(pitches.length);
		// int index2 = (int) Math.floor(Math.random() * 100 %
		// durations.length);
		System.out.println(index);
		//n.setPitchType(Note.MIDI_PITCH);
		
		n.setPitch(bm.getNextPitch(0));
		//n.setPitch(pitches[index]);
		// n.setOffset(0.0);
		// n.setDynamic((int) (Math.random() * 80 + 45));
		// n.setPan(panPosition);
		double duration = 0.0;
		System.out.println("X " + x);
		if (useCell) {
			if((currentRCell == null) || count == currentRCell.length){
				currentRCell = DurationCellRepository.getCellByInput((float)x);
				count = 0;
			} 
			duration = getRhythmValueByDuration(currentRCell[count]);
			count = count + 1;

		} else {
			int index2 = Math.round(Utils.map((float) x, 0.0f, 1.0f, 0,
					durations.length - 1));
			duration = durations[index2];
		}
		System.out.println("Duration: " + duration);
		
		n.setRhythmValue(duration);
		n.setDuration(n.getRhythmValue());
		
		if(count == 1){
			n.setDynamic(100);
		} else {
			n.setDynamic(87);
		}
		
		if(Math.random() <= this.y){
			n.setPitch(Note.REST);
		}
		
		return n;
	}

	public void setValueX(double x) {
		this.x = x;
	}

	public void setValueY(double y) {
		this.y = y;
	}

	// added for control change
	public synchronized void externalAction(Object obj, int actionNumber) {
		if (actionNumber == 1) {
			JSlider slider = (JSlider) obj;
			double filterCutoff = (double) (slider.getValue() * 100);
			for (int i = 0; i < inst.length; i++) {
				double[] values = { filterCutoff };
				inst[i].setController(values);
			}
		}
	}
}
